package com.clerkq.FlvPlayer
{
	
	import com.clerkq.FlvPlayer.event.VideoEvent;
	import com.library.core.IDisposable;
	import com.library.core.UIObject;
	import com.library.utils.Tick.Tick;
	import com.library.utils.Tick.TickEvent;
	
	import flash.events.NetStatusEvent;
	import flash.media.SoundTransform;
	import flash.media.Video;
	import flash.net.NetConnection;
	import flash.net.NetStream;

	public class VideoDisplay extends UIObject implements IDisposable
	{
        private var _isPaused:Boolean;// = false
        private var _nc:NetConnection;
        private var _ns:NetStream;
        private var _video:Video;
        private var _url:String;
        private var _client:Object;
        private var _duration:Number;// = 0
        
		public function VideoDisplay(width:Number, height:Number)
		{
			super();
			_duration = 0;
            _isPaused = false;
            
            // Create Video
            _video = new Video();
            _video.width = width;
            _video.height = height;
            addChild(_video);
            _nc = new NetConnection();
		}
		
        public function close():void{
            if (_ns != null){
            	_ns.removeEventListener(NetStatusEvent.NET_STATUS, netStatus);
                _ns.close();                
            };
            if (_nc != null){
                _nc.close();
            };
            Tick.getInstance().removeEventListener(TickEvent.TICK, updateTime);
        }
        
        public function Dispose():void{
            close();
            removeAllChilds();
        }
        
        private function updateTime(evt:TickEvent):void{
            //_time = _ns.time;
            dispatchEvent(new VideoEvent(VideoEvent.NEW_TIME, true, true));
        }
        
        public function play(videoUrl:String=""):void{
            close();
            _url = videoUrl;      
            _nc.connect(null);
            _ns = new NetStream(_nc);
            _ns.bufferTime = 5;
            _ns.addEventListener(NetStatusEvent.NET_STATUS, netStatus);
            _client = new Object();
            _client.onMetaData = onMetaData;
            _ns.client = _client;
            _video.attachNetStream(_ns);
            _ns.play(_url);
        }
        
        public function pause():void{
        	if (_ns == null) return;
            _isPaused = true;
            _ns.pause();
        }
        
        public function resume():void{
        	if (_ns == null) return;
            _isPaused = false;
            if (_ns.time < int(_duration)){
                _ns.resume();
            };
        }
        
        public function seek(percent:Number):void{
        	if (_ns == null) return;
	        _ns.seek(_duration * percent);
        }
        
        public function resumeAfterSeek():void{
        	if (_ns == null) return;
            if (_isPaused){
                pause();
            } else {
                resume();
            };
        }
        
        public function pauseForSeek():void{
        	if (_ns == null) return;
            _ns.pause();
        }
        
        // Events ///////////////////////////
        private function netStatus(evt:NetStatusEvent):void{
            switch (evt.info.code){
                case "NetStream.Buffer.Full":
                    dispatchEvent(new VideoEvent(VideoEvent.ON_PLAY, false, false));
                    dispatchEvent(new VideoEvent(VideoEvent.ON_BUFFER_FULL, false, false));
                    break;
                case "NetStream.Play.Stop":
                    if (_duration > 0 && Math.floor(_duration) == Math.floor(_ns.time)){
                        dispatchEvent(new VideoEvent(VideoEvent.ON_END, false, false));
                    };
//                    dispatchEvent(new VideoEvent(VideoEvent.ON_STOP, false, false));
                    break;
                case "NetStream.Buffer.Empty":
                    dispatchEvent(new VideoEvent(VideoEvent.ON_BUFFER_EMPTY));
                    break;
                case "NetStream.Seek.Failed":
                	trace("The seek fails, which happens if the stream is not seekable.");
                	break;
                case "NetStream.Seek.InvalidTime":
                	_ns.seek(evt.info.details);
                	trace(	"seek or play past the end of the video data.");
                	break;
            };
        }
        
        private function onMetaData(info:Object):void{
        	_duration = info.duration;
        	//trace(_duration);
            Tick.getInstance().addEventListener(TickEvent.TICK, updateTime);
        }
        
        // Get and Set /////////////////////
        public function set volume(volume:Number):void{
        	if (_ns == null) return;
			var soundTransform:SoundTransform = _ns.soundTransform;
			soundTransform.volume = volume;
			_ns.soundTransform = soundTransform;
        }
        public function get video():Video{
            return _video;
        }
        
        public function get duration():Number{
            if (_duration > 0){
                return (_duration);
            };
            return (0);
        }
        public function get percentPlayed():Number{
            var percent:Number = (time / duration);
            if (percent > 0){
                return percent;
            };
            return (0);
        }
        public function get percentLoaded():Number{
            var percent:Number = (_ns.bytesLoaded / _ns.bytesTotal);
            return percent;
        }
        
        public function get time():int{
            return _ns.time;
        }
	}	
}
